<template>
    <n-button
    :disabled="!fileListLength"
    style="margin-bottom: 12px"
    @click="handleClick"
  >
    上传文件
  </n-button>
  <n-upload
    ref="upload"
    action="https://www.mocky.io/v2/5e4bafc63100007100d8b70f"
    :default-upload="false"
    max="1"
    @change="handleChange"
  >
    <n-button>选择文件</n-button>
  </n-upload>
</template> 
<script lang='ts' setup>
    import { ref,reactive } from 'vue'
    import type { UploadInst, UploadFileInfo } from 'naive-ui'
    import SparkMD5 from 'spark-md5'
    import MyRequest from '@/service/service'
    import { type } from 'os';
    import { debug } from 'console';
    
    const fileListLength = ref(0)
    const upload = ref<UploadInst | null>(null)
    let list:any =  reactive([])
    function handleChange (options: { fileList: UploadFileInfo[] }) {
        fileListLength.value = options.fileList.length
        list = options.fileList
    }
    
    const changeBuffer:any = (file:File) => {
        return new Promise(resolve => {
            let fileReader = new FileReader();
            fileReader.readAsArrayBuffer(file);
            fileReader.onload = (ev) => {
                let buffer = ev.target!.result,
                    spark = new SparkMD5.ArrayBuffer(),
                    HASH,
                    suffix;
                spark.append(buffer);
                HASH = spark.end();
                suffix = /\.([a-zA-Z0-9]+)$/.exec(file.name)![1];
                resolve({
                    buffer,
                    HASH,
                    suffix,
                    filename: `${HASH}.${suffix}`
                });
            };
        });
    };
    const getAlready = function(HASH){
        return new Promise(resolve => {
            type Req = {
                HASH:string
            }
            type Res = {
                fileList:object
            }
            MyRequest<Req,Res>({
                name: 'upload-already',
                params:{
                    HASH
                },
            }).then((res)=>{
                resolve(res.data.fileList);
            })
        })
    }
    async function  handleClick (){
        let file = list[0].file;
        // 获取文件的HASH
        let already:any = [],
        {
            HASH,
            suffix
        } = await changeBuffer(list[0].file);
        try {
            already = await getAlready(HASH)// 获取已经上传的切片信息
        } catch (err) {
            console.log(err)
        }
        // 实现文件切片处理 「固定数量 & 固定大小」
        let max = 1024 * 100,
            count = Math.ceil(file.size / max),
            index = 0,
            chunks = [];
        if (count > 100) {
            max = file.size / 100;
            count = 100;
        }
        while (index < count) {
            console.log(index,count)
            chunks.push({
                file: file.slice(index * max, (index + 1) * max),
                filename: `${HASH}_${index+1}.${suffix}`
            });
            index++;
        }
        console.log(chunks.length,'chunks')
        // 上传成功的处理
        index = 0;
        const complate = async () => {
            // 当所有切片都上传成功，我们合并切片
            index ++
            if (index < count) return;
            type Req = {}
            try {
                await MyRequest<Req>({
                    name: 'upload-merge',
                    body:{
                        HASH,
                        count
                    },
                }).then((res)=>{
                    if(res.code==0){
                        console.log('文件上传成功')
                    }
                })
            } catch (err) {
                console.log('切片合并失败')
            }
        };
        // 把每一个切片都上传到服务器上
        chunks.forEach((chunk,index) => {
            // 已经上传的无需在上传
            if (already.length > 0 && already.includes(chunk.filename)) {
                complate();
                return;
            }
            console.log(index)
            let fm = new FormData;
            fm.append('file', chunk.file);
            fm.append('filename', chunk.filename);
            type Req = {}
            MyRequest<Req>({
                name: 'upload-chunk',
                body:fm,
            }).then((res)=>{
                debugger
                complate();
                return Promise.reject(res.data.codeText);
            }).catch((err)=>{

            })
        });
    }
    const chunkUpload = function(){}
    
</script>
<style lang="scss" scoped>

</style>
